#include "EventLoop.h"
#include "Poller.h"
#include "Logger.h"
#include "Channel.h"

#include <sys/eventfd.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <memory>

// 防止一个线程创建多个eventloop __thread 就是一个线程单独一个
__thread EventLoop *t_loopInThisThread = nullptr;

// 定义默认的Poller IO超时时间
const int kPollTimeMs = 10000;

// 用于唤醒subreactor
int creatEventfd()
{
    int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if (evtfd < 0)
    {
        LOG_FATAL("eventfd err :%d", errno);
    }
    return evtfd;
}

EventLoop::EventLoop() : looping_(false), quit_(false), callingPendingFunctors_(false),
                         threadId_(CurrentThread::tid()), poller_(Poller::newDefaultPoller(this)),
                         wakeupFd_(creatEventfd()), wakeupChannel_(new Channel(this, wakeupFd_))
{
    LOG_DEBUG("EventLoop created %p in thread %d\n", this, threadId_);
    if (t_loopInThisThread)
    {
        LOG_FATAL("Another EventLoop %p exists in this thread %d", t_loopInThisThread, threadId_);
    }
    else
    {
        t_loopInThisThread = this;
    }

    // 设置wakeupfd的事件类型和发生事件的回调操作
    wakeupChannel_->setReadCallback(std::bind(&EventLoop::handleRead, this));
    // 监听wakeupChannel的读事件,
    wakeupChannel_->enableReading();
}

EventLoop::~EventLoop()
{
    wakeupChannel_->disableALL();

    wakeupChannel_->remove();
    ::close(wakeupFd_);
    t_loopInThisThread = nullptr;
}

void EventLoop::handleRead()
{
    uint64_t one = 1;
    ssize_t n = read(wakeupFd_, &one, sizeof(one));
    if (n != sizeof(one))
    {
        LOG_ERROR("EventLoop::handleRead() reads %ld bytes instead of 8", n);
    }
}

// 开启事件循环
void EventLoop::loop()
{
    looping_ = true;
    quit_ = false;

    LOG_INFO("EventLoop %p start loop \n", this);

    while (!quit_)
    {
        activeChannel_.clear();
        // epoll_wait
        pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannel_); // 得到了发生事件的channel
        for (Channel *channel : activeChannel_)
        {
            // 通过channel调用对应的事件
            channel->headleEvent(pollReturnTime_);
        }
        // 执行当前eventloop事件循环需要的回调操作，比如mainreactor需要把连接的fd分发给subreactor，
        // 当fd里面有mainreactor的eventfd，那就需要执行pendingFunctors_中的回调(mainreactor注册的)
        doPendingFunctors();
    }

    LOG_INFO("EventLoop %p stop loop\n", this);
}
// 退出事件循环
void EventLoop::quit()
{
    quit_ = true;

    // 如果在其他线程调用本线程的quit，但是本线程可能在休眠状态，因此需要唤醒
    if (!isInLoopThread())
    {
        wakeup();
    }
}

// 在当前loop中执行
void EventLoop::runInLoop(Functor cb)
{
    if (isInLoopThread()) // 在当前的loop线程中执行
    {
        cb();
    }
    else // 在非当前线程中执行执行cb，需要唤醒loop所在线程，cb
    {
        queueInLoop(cb);
    }
}
// 在其他线程中执行
void EventLoop::queueInLoop(Functor cb)
{
    {
        std::unique_lock<std::mutex> lock(mutex_);
        pendingFunctors_.emplace_back(cb);
    }

    // 唤醒对应的需要执行回调的loop的线程
    if (!isInLoopThread() || callingPendingFunctors_)
    {
        wakeup();
    }
}

//唤醒loop所在的线程
void EventLoop::wakeup()
{
    uint64_t one = 1;
    ssize_t n = write(wakeupFd_, &one, sizeof one); 
    if(n != sizeof one)
    {
        LOG_ERROR("EventLoop wakeup write %lu insteat of 8\n", n);
    }
}

// EventLoop调用poller的放啊
void EventLoop::updateChannel(Channel *channel)
{
    poller_->updateChannel(channel);
}
void EventLoop::removeChannel(Channel *channel)
{
    poller_->removeChannel(channel);
}
bool EventLoop::hasChannel(Channel *channel)
{
    return poller_->hasChannel(channel);
}
void EventLoop::doPendingFunctors()
{
    std::vector<Functor> functors;
    callingPendingFunctors_ = true;
    {
        std::unique_lock<std::mutex> lock(mutex_);
        functors.swap(pendingFunctors_); 
    }

    for(const Functor& functor:functors)
    {
        functor();//执行当前loop需要的回调操作
    }
    callingPendingFunctors_ = false;
}